/*

Written by Steve Maser, PTC 3/5/2002, Updated 9/2003 (updated for Rev 7 April, 2004)


This is a cool webject that will retrieve any URL's content and stream it back to be used within a task
No sense to use this in JSP, just reDirect to the URL you send this webject.  This is for SOAP, for Example.


You must add this line to your $WTHOME/codebase/wt.adapter.delegates.properties file to enable this webject.

GETURLCONTENT.WCTYPE|java.lang.Object=ext.adapter.content.GetUrlContent

## xconfmanager -s <property_name>=<property_value> -t <full_path_property_file> -p


WEBJECT:

   		<ie:webject name="get-Urlcontent" type="OBJ">
   			  <ie:param name="INSTANCE"		data="${properties[0]wt.federation.ie.VMName[0]}"/>
   		      <ie:param name="AUTHORIZATION" data="${@SERVER[]authorization[]}"/>
   			  <ie:param name="URL"       data="http://copper/Windchill/wtcore/jsp/wt/portal/index.jsp"/>
   			  <ie:param name="FILENAME" data="myFile.html" default="from URL"/>
   			  <ie:param name="NAME" data="wcadmin" default="filename"/>
   			  <ie:param name="CONTENTTYPE" data="wcadmin" default="gets from contentStream"/>

				// optional if you are going to a remote machine (otherwise, always will pass AUTHORIZATION value to URL)
			  <ie:param name="URLDBUSER" data="wcadmin"/>
   			  <ie:param name="URLPASSWD" data="wcadmin"/>

   			  // optionals if you Capture this in a I*E Group instead of Streaming back in task
   			  <ie:param name="GROUP_OUT" data="stream"/>
   			  <ie:param name="RETURN" data="STRING|STREAM" default="string"/>
   			  <ie:param name="ATTRIBUTE" data="stream" default="stream"/>
   			  <ie:param name="ENCODE"    data="TRUE" default="false"/>
   			  <ie:param name="ENCODETYPE"    data="BASE64" default="BASE64"/>

   			  // optional if you want to store the file on the server
   			  <ie:param name="DIRECTORY" data="C:/Temp"/>
   			  <ie:param name="GROUP_OUT" data="fileLocation"/>

		</ie:webject>

*/

package com.ptc.core.adapter.server.impl;

import wt.adapter.*;
//import com.infoengine.log.ServiceWriter;
import com.infoengine.object.factory.*;
import com.infoengine.object.*;
import java.io.*;
//import java.util.*;
//import java.lang.StringBuffer;
//import wt.adapter.*;
//import wt.fc.*;
import wt.util.*;
//import wt.content.*;
import java.net.*;
import com.infoengine.util.Base64;
//import wt.pom.*;

//http://localhost/Windchill/codebase/wt/clients/library/api/com/ptc/core/adapter/server/impl/AbstractWebjectDelegate.html
//import com.ptc.core.adapter.server.impl.AbstractWebjectDelegate;


public class GetUrlContent extends AbstractWebjectDelegate {

    public Task invoke(Task task) throws WTException {
		Webject webject = task.getWebject();

        // Processing Variables
			//String viewurl = "";


/* GET INPUTS */

		// Get the REQUIRED attributes

		String urlstr;
		if ((urlstr= webject.paramValue("URL",null))==null)
			throw new WebjectServiceException("URL is a required Parameter");
		System.out.println("Open URL: " + urlstr);

		// Other Optional Variables (more are used in TRY)
		String dbuser= webject.paramValue("DBUSER",null);
		String passwd= webject.paramValue("PASSWD",null);
		String name= webject.paramValue("NAME",null);
		String directory= webject.paramValue("DIRECTORY",null);
		String filename= getFileName(webject);
		if(name==null) name=filename;
		String contentType= webject.paramValue("CONTENTTYPE",null);
		String groupOut= webject.paramValue("GROUP_OUT",null);
		String attName= webject.paramValue("ATTRIBUTE","stream");
/* DO THE WORK */

		try{

			// get the content via URL
			Task task1 = new Task();
			URL url = new URL(urlstr);
			HttpURLConnection httpUrlConnection = (HttpURLConnection)url.openConnection();
			httpUrlConnection.setDoInput(true);
			httpUrlConnection.setUseCaches(false);
			if(dbuser != null && passwd != null)
				httpUrlConnection.setRequestProperty("Authorization", "Basic " + Base64.encode(dbuser + ':' + passwd));
			else if(webject.paramValue("AUTHORIZATION",null)!=null) httpUrlConnection.setRequestProperty("Authorization",webject.paramValue("AUTHORIZATION"));
			InputStream is = httpUrlConnection.getInputStream();
			int errorCode = httpUrlConnection.getResponseCode();
			if (contentType==null) contentType=httpUrlConnection.getContentType();
			if(errorCode < 200 || errorCode > 299) {
				System.out.println("unable to read URL" + urlstr+" Error Code"+errorCode);
				System.out.println("MESSAGE:  " + httpUrlConnection.getResponseMessage());
				throw new WebjectServiceException("unable to get Content, check Logs, URL, or authentication. Error Code:  "+errorCode+"  Reason:  "+httpUrlConnection.getResponseMessage());
			}
			else System.out.println("Got Data from: " + urlstr +  "--- Content Type:  "+contentType);
			System.out.println("GROUP_OUT="+groupOut);
			// write content into returned Task
			if (groupOut==null|| groupOut.length()==0){
				IeMultipartOutputStream outIe = writeBlobStream(task,is, name, filename, contentType);
				if(is != null) is.close();
				task1.setOutputStream(outIe);
			}
			else if(directory!=null) {
				System.out.println("Will Stream into File on Server at "+directory);
				File output=writeToFile(is,name,directory);
				Element row=new Element();
				row.addAtt(new Att("directory", directory) );
				row.addAtt(new Att("fullPath", output.getPath()) );
				row.addAtt(new Att("fileName", output.getName()) );
				row.addAtt(new Att("size", ""+output.length()) );
				Group group=new Group();
				group.setName(groupOut);
				group.addElement(row);
				task1.addVdb(group);
			}
			else {
				System.out.println("Will Stream into Group_OUT="+groupOut+ " att="+attName);
				Group group=new Group();
				group.setName(groupOut);
				group.setType(1);
				String className = webject.paramValue("CLASS", null);
				if(className != null) group.setClassName(className);
				else group.setClassName(group.getClassName());
				task1.addVdb(group);
				Element theRow = new Element();

				// write inputStream to String
				BufferedInputStream  bis = new BufferedInputStream(is);
				if(webject.paramValue("RETURN","STRING").equalsIgnoreCase("STRING")) {
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					System.out.println("Writing content to String");
					byte[] buff = new byte[2048];
					int bytesRead;
					while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) baos.write(buff, 0, bytesRead);
					System.out.println("Content Written to String");
					String stream=baos.toString();
					bis.close();
					baos.close();
					if(webject.paramValue("ENCODE","").equalsIgnoreCase("True")) {
						System.out.println("Will Encode Output");
						if (webject.paramValue("ENCODETYPE","Base64").equalsIgnoreCase("Base64"))
							stream=Base64.encode(stream.toString());
						else throw new WebjectServiceException("BASE64 only Supported Encoding");
					}
					theRow.addAtt(new Att (attName,stream));
					if(is != null) is.close();
				}
				else {
					theRow.addAtt(new Att (attName,is));
				}

				// now setup Output Group

				theRow.addAtt(new Att ("name",name));
				theRow.addAtt(new Att ("fileName",filename));
				theRow.addAtt(new Att ("contentType",contentType));
				group.addElement(theRow);

				System.out.println("Content Written to Group");
				task1.addVdb(group);
				System.out.println("Webject Done");
			}

		return task1;
		}
		catch(MalformedURLException ex){
			ex.printStackTrace();
			throw new WTException(ex);
		}
		catch(IOException ex){
			ex.printStackTrace();
			throw new WTException(ex);
		}
		catch(Exception ex){
			ex.printStackTrace();
			throw new WTException(ex);
		}
	}

	public static IeMultipartOutputStream writeBlobStream(Task myTask, InputStream is, String name, String filename, String contentType)
		throws WebjectServiceException
	    {
	        IeMultipartOutputStream ieOut = null;
	        Object obj = myTask.getRequest().getMetaValue("OUTPUT_STREAM");
	        if(obj instanceof IeMultipartOutputStream)
	            ieOut = (IeMultipartOutputStream)obj;
	        try
	        {
	            System.out.println("Number of bytes in content = " + is.available());
	            ieOut.writeBlob(is, "Blob-Results", filename, contentType);
	            ieOut.flush();
	            ieOut.writeEOF();
	        }
	        catch(Exception exception)
	        {
	            exception.printStackTrace();
	            System.out.println("Error writing blob to ieOutput stream...");
				throw new WebjectServiceException("Error writing ieMultipartOutputStream");
	        }
	        return ieOut;
    }

	private static File writeToFile(InputStream is, String name,String filedir) throws Exception {
		File file = new File(filedir);
		if(!file.exists() || !file.isDirectory()) {
			if(VERBOSE) System.out.println("Directory not found, Try to make Directory:  "+filedir);
			file.mkdirs();
		}
		String filename=filedir+File.separator+name;
		IeMultipartInputStream iemultipartinputstream = new IeMultipartInputStream(is,"Blob-Results","file","file");
		FileOutputStream fileoutputstream = new FileOutputStream(filename);
		if(VERBOSE) System.out.println("start writing file to: "+filename);
		iemultipartinputstream.readBlob(fileoutputstream);
		if(VERBOSE) System.out.println("Successfully wrote file:  "+filename);
		iemultipartinputstream.close();
		fileoutputstream.close();
		return new File(filename);
	}

	private static String getFileName(Webject webject) throws WTException {
		String name= webject.paramValue("NAME",null);
		if(name ==null){
			String urlstr= webject.paramValue("URL",null);
			try {
				URL url = new URL(urlstr);
				name = url.getFile();
			}
			catch (IOException ioex) {
				ioex.printStackTrace();
				throw new WTException(ioex);
			}
			if (name.lastIndexOf("/") >=0) {
				if (name.length() == name.lastIndexOf("/")+1) name=null;
				else name=name.substring(name.lastIndexOf("/")+1);
			}
			if(name.indexOf("?") >0) name=name.substring(0,name.indexOf("?"));
		}
		if (name ==null) name="UNKNOWN";
		return name;
	}

}







